package cn.sc.summer.constant.util;

import cn.hutool.core.collection.CollUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.ServiceLoader;

/**
 * 类名：SPI机制获取指定接口的实现类
 *
 * @author a-xin
 * @date 2024/8/28 13:49
 */
public class SPIExtensionUtil {

    /**
     * 加载所有接口实现类并校验
     *
     * @param clazz 接口
     * @param <T>   接口类型
     * @return 所有实现类
     */
    public static <T> List<T> loadExtension(Class<T> clazz) {
        if (!clazz.isInterface()) {
            throw new IllegalArgumentException(String.format("The [%s] is not a interface!", clazz.getName()));
        }
        List<T> extensions = findExtensions(clazz);
        if (CollUtil.isNotEmpty(extensions)) {
            if (extensions.size() > 1) {
                throw new IllegalArgumentException(String.format("There is multiple implements of :[%s]!", clazz.getName()));
            } else {
                return extensions;
            }
        } else {
            throw new IllegalArgumentException(String.format("There is no implements of :[%s]!", clazz.getName()));
        }
    }

    /**
     * 通过SPI机制获取指定接口的所有实现类型
     *
     * @param clazz 接口
     * @param <T>   接口类型
     * @return 所有实现类
     */
    private static <T> List<T> findExtensions(Class<T> clazz) {
        List<T> list = new ArrayList<>();
        for (T t : ServiceLoader.load(clazz, SPIExtensionUtil.class.getClassLoader())) {
            list.add(t);
        }
        return list;
    }

}

